package com.thinkgem.book.common.utils;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.Provider;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.sql.SQLException;
import java.util.Random;

/**
 * RSA算法加密/解密工具类。
 *
 * @author tonglei
 * @version 1.0.0, 2015-05-14
 */
public class RSAUtils
{
    private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
    /**
     * 算法名称
     */
    private static final String ALGORITHOM = "RSA";

    /**
     * 默认的安全服务提供者
     */
    private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();

    private RSAUtils()
    {
    }

    /**
     * 使用指定的公钥加密数据。
     *
     * @param publicKey 给定的公钥。
     * @param data      要加密的数据。
     * @return 加密后的数据。
     */
    public static byte[] encrypt(PublicKey publicKey, byte[] data)
        throws Exception
    {
        Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
        ci.init(Cipher.ENCRYPT_MODE, publicKey);
        return ci.doFinal(data);
    }

    /**
     * 使用给定的公钥加密给定的字符串。
     * <p/>
     * 若 {@code publicKey} 为 {@code null}，或者 {@code plaintext} 为 {@code null} 则返回 {@code
     * null}。
     *
     * @param publicKey 给定的公钥。
     * @param plaintext 字符串。
     * @return 给定字符串的密文。
     */
    public static String encryptString(PublicKey publicKey, String plaintext)
    {
        if (publicKey == null || plaintext == null)
        {
            return null;
        }
        byte[] data = plaintext.getBytes();
        try
        {
            byte[] en_data = RSAUtils.encrypt(publicKey, data);
            return new String(Hex.encodeHex(en_data));
        }
        catch (Exception ex)
        {
            LOGGER.error(ex.getCause().getMessage());
        }
        return null;
    }

    /**
     * 返回已初始化的默认的公钥。
     *
     * @throws Exception
     * @throws SQLException
     */
    public static RSAPublicKey getDefaultPublicKey() throws Exception
    {
        // 初始化RSA加密参数
        RSAKeyParameters rsaKeyParameters = new RSAKeyParameters(false,
                new BigInteger("98512282862705199621660053246429064827027756292255053264614908624258661307811458648601076294029711018635745707137315511333738635761852937831411589435094460974617063371179077507387047420140476693428647678565621610929202184262110246885432983496072518478188574955587274815681905611293404451359785981401053928637"),
                new BigInteger("65537"));
        // 返回公钥对象
        return new LjRSAPulicKey(rsaKeyParameters);
    }

    public static String getRandomString(int length) {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz%!@#%";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}
